/*
 * @(#)FieldReflect.java 1.0 2009/04/15
 */
package stardust.core.java.reflect;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;


/**
 * <code>FieldReflect</code> 类提供反射字段的操作，并支持除数组外的自动类型转换。
 * <p/>
 * @version 1.0, 2009/04/15
 * @author ChenChang
 */
public class FieldReflect<T>
{

  /*
   * 在 Bean 模式时的反射源。
   */
  private T object;

  /**
   * 获取反射的源对象引用。
   * <p/>
   * @param object
   * 反射所作用的源对象。
   */
  public void setObject(T object)
  {
    if (object == null)
    {
      throw null;
    }

    this.object = object;
  }

  /**
   * 获取反射的源对象引用。
   * <p/>
   * @return 反射所作用的源对象。
   */
  public T getObject()
  {
    return this.object;
  }

  /**
   * 获取一个 Bean 模式的反射器，可以简化对象属性的 Get/Set 操作。
   */
  public FieldReflect()
  {
    this(null);
  }

  /**
   * 获取一个 Bean 模式的反射器，可以简化对象属性的 Get/Set 操作。
   * <p/>
   * @param object
   * 一个反射源对象，如果为 <tt>null</tt> 值会引发 {@link NullPointerException} 异常。
   */
  public FieldReflect(T object)
  {
    this.object = object;
  }

  /**
   * 按字段名称查找字段，包括私有的和父类型中定义的字段。
   * <p/>
   * @param c
   * 在这个参数中查找字段，它是一个 {@link java.lang.Class} 类型。
   * @param name
   * 需要查找的字段名称。
   * @param caseSensitive
   * 是否启用大小写敏感。
   * <p/>
   * @return 如果找到该字段将返回 {@link java.lang.reflect.Field} 对象，未找到返回 <tt>null</tt>
   * 值。
   */
  public static Field findField(Class c, String name, boolean caseSensitive)
  {
    Field[] fs = getFields(c);

    for (int i = 0; i < fs.length; i++)
    {
      if ((caseSensitive == true && fs[i].getName().equals(name))
          || (caseSensitive == false && fs[i].getName().equalsIgnoreCase(name)))
      {
        return fs[i];
      }
    }
    return null;
  }

  /**
   * 获取所有的字段，包括私有的和父类型中定义的字段。
   */
  public static Field[] getFields(Class c)
  {
    List<Field> fields = new ArrayList<Field>();
    Field[] fs;

    do
    {
      fs = c.getDeclaredFields();
      for (int i = 0; i < fs.length; i++)
      {
        fields.add(fs[i]);
      }
    }
    while ((c = c.getSuperclass()) != Object.class);

    return fields.toArray(new Field[fields.size()]);
  }

  public static Object getFieldValue(Object o, String field)
  {
    Field f = findField(o.getClass(), field, false);

    return getFieldValue(o, f);
  }

  public static Object getFieldValue(Object o, Field field)
  {
    Field f = field;

    if (f == null)
    {
      return null;
    }
    else
    {
      try
      {
        f.setAccessible(true);
        return f.get(o);
      }
      catch(Exception ex)
      {
        return null;
      }
    }
  }

  public static void setFieldValue(Object o, String field, Object value)
  {
    Field f = findField(o.getClass(), field, false);

    if (f != null)
    {
      setFieldValue(o, f, value);
    }
  }

  public static void setFieldValue(Object o, Field f, Object value)
  {
    Class c = f.getType();
    Object cast;

    if (f != null)
    {
      cast = TypeUtils.castToType(value, c);
      try
      {
        f.setAccessible(true);
        f.set(o, cast == null ? value : cast);
      }
      catch(Exception ex)
      {
      }
    }
  }

}
